package com.swak.utils;

/**
 * 二进制相关操作
 * 
 * @author lifeng
 * @date 2020年9月7日 下午4:47:53
 */
public class Bits {

	/**
	 * 查找哪一位是指定的值
	 * 
	 * @param num
	 * @param value
	 * @return
	 */
	public static int search(long num, long v) {
		return search(0, 63, num, v);
	}

	static int search(int L, int R, long num, long v) {
		if (R < L) {
			return -1;
		}
		int mid = (L + R) / 2;
		if (Bits.getBit(num, mid) == v) {
			return mid;
		}
		int index = search(L, mid - 1, num, v);
		return index == -1 ? search(mid + 1, R, num, v) : index;
	}
	
	/**
	 * 得到第几位的值： 0 or 1
	 * 
	 * @param num    原始值
	 * @param offset 偏移量 从 0开始
	 * @return
	 */
	public static int getBit(int num, int offset) {
		if (!(offset >= 0 && offset <= 31)) {
			throw new IllegalArgumentException("Offset is Over!");
		}
		return (num >> offset & 1);
	}

	/**
	 * 设置bit值，只能设置 0 或 1
	 * 
	 * @param num    原始值
	 * @param offset 偏移量 从 0开始
	 * @param value  0 or 1
	 */
	public static int setBit(int num, int offset, int value) {
		if (!(offset >= 0 && offset <= 31)) {
			throw new IllegalArgumentException("Offset is Over!");
		}
		if (!(value == 0 || value == 1)) {
			throw new IllegalArgumentException("Value is only in (0, 1)!");
		}
		if (value == 0) {
			return num & ~(1 << offset);
		}
		return num | (1 << offset);
	}

	/**
	 * 得到第几位的值： 0 or 1
	 * 
	 * @param num    原始值
	 * @param offset 偏移量 从 0开始
	 * @return
	 */
	public static long getBit(long num, int offset) {
		if (!(offset >= 0 && offset <= 63)) {
			throw new IllegalArgumentException("Offset is Over!");
		}
		return (num >> offset & 1);
	}

	/**
	 * 设置bit值，只能设置 0 或 1
	 * 
	 * @param num    原始值
	 * @param offset 偏移量 从 0开始
	 * @param value  0 or 1
	 */
	public static long setBit(long num, int offset, int value) {
		if (!(offset >= 0 && offset <= 63)) {
			throw new IllegalArgumentException("Offset is Over!");
		}
		if (!(value == 0 || value == 1)) {
			throw new IllegalArgumentException("Value is only in (0, 1)!");
		}
		if (value == 0) {
			return num & ~(1 << offset);
		}
		return num | (1 << offset);
	}

	/**
	 * 得到指定位置的值
	 * 
	 * @param num   数据
	 * @param group 分组
	 * @param width 宽度
	 * @return
	 */
	public static int getBits(long num, int group, int width) {
		int offset = group * width;
		if (!(offset >= 0 && offset <= 63)) {
			throw new IllegalArgumentException("Offset is Over!");
		}
		long mask = ~(0xff << width);
		return (int) (num >> offset & mask);
	}

	/**
	 * 得到指定位置的值
	 * 
	 * @param num   数据
	 * @param group 分组
	 * @param width 宽度
	 * @param value 要设置的值
	 * @return
	 */
	public static long setBits(long num, int group, int width, int value) {
		int offset = group * width;
		if (!(offset >= 0 && offset <= 63)) {
			throw new IllegalArgumentException("Offset is Over!");
		}
		return num | (value << offset);
	}
}